# gozerbot/monitor.py
#
#

""" 
    This module contains the Monitor base class use to implement callbacks for 
    the bot's output. Used in logging plugins. The actual monitor objects live
    irc and xmpp submodules.

"""

__status__ = "seen"

## gozerbot imports

from gozerbot.config import config
from gozerbot.stats import stats
from utils.log import rlog
from utils.exception import handle_exception
from utils.trace import calledfrom
from config import config
from threads.threadloop import ThreadLoop
from runner import waitrunners
import threads.thr as thr

## basic imports

import Queue
import sys

## Monitor class

class Monitor(ThreadLoop):

    """ monitor base class. used as base class for jabber and irc output monitoting. """

    def __init__(self, name="monitor"):
        ThreadLoop.__init__(self, name)        
        self.outs = []

    def add(self, name, callback, pre, threaded=False):
        """ add a monitoring callback. """
        name = name or calledfrom(sys._getframe(0))
        if config['loadlist'] and name not in config['loadlist']: return False
        self.outs.append([name, callback, pre, threaded, False])
        rlog(0, self.name, 'added monitor %s (%s)' % (name, str(callback)))
        return True

    def disable(self, name):
        name = name.lower()
        for i in range(len(self.outs)-1, -1, -1):
            if self.outs[i][0] == name: self.outs[i][4] = False

    def activate(self, name):
        name = name.lower()
        for i in range(len(self.outs)-1, -1, -1):
            if self.outs[i][0] == name: self.outs[i][4] = True
        
    def unload(self, name):
        """ delete monitor callback. """
        name = name.lower()
        nr = 0
        for i in range(len(self.outs)-1, -1, -1):
            if self.outs[i][0] == name: del self.outs[i] ; nr += 1
        return nr
   
    def handle(self, *args, **kwargs):
        """ check if monitor callbacks need to be fired. """
        nr = 0
        for i in self.outs:
            if not i[4]: continue
            try:
                if i[2]:
                    stats.up('monitors', thr.getname(str(i[2])))
                    rlog(-10, 'monitor', 'checking inloop %s' % str(i[2]))
                    doit = i[2](*args, **kwargs)
                else: doit = 1
            except Exception, ex:
                handle_exception()
                doit = 0
            if doit:
                rlog(0, 'monitor', 'excecuting monitor callback %s' % i[0])
                stats.up('monitors', thr.getname(str(i[1])))
                if not i[3]: waitrunners.put("monitor-%s" % i[0], i[1], *args)
                else: thr.start_new_thread(i[1], args, kwargs)
                nr += 1
        return nr
